home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-23 | 53.5 KB | 1,569 lines |
- Newsgroups: comp.sources.misc
- From: Raymond Chen <rjc@math.princeton.edu>
- Subject: v22i057: wp2x - WordPerfect4.2 to Whatever converter, Part03/03
- Message-ID: <1991Aug23.184927.9807@sparky.IMD.Sterling.COM>
- X-Md4-Signature: cbfc067495ccec7d7a03b00f7b44f851
- Date: Fri, 23 Aug 1991 18:49:27 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Raymond Chen <rjc@math.princeton.edu>
- Posting-number: Volume 22, Issue 57
- Archive-name: wp2x/part03
- Environment: Amiga, MS-DOS, UNIX, ANSI-C
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 3)."
- # Contents: wp2x.c
- # Wrapped by rjc@tomato on Wed Aug 21 00:08:06 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'wp2x.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wp2x.c'\"
- else
- echo shar: Extracting \"'wp2x.c'\" \(51514 characters\)
- sed "s/^X//" >'wp2x.c' <<'END_OF_FILE'
- X/* $Id: wp2x.c 1.10 91/08/18 15:05:41 raymond Exp $ */
- X
- X/* Before compiling, read the section titled `portability concerns'. */
- X
- X/************************************************************************
- X * $Log: wp2x.c $
- X * Revision 1.10 91/08/18 15:05:41 raymond
- X * Descriptor file stuff.
- X *
- X * Revision 1.9 91/08/06 09:08:09 raymond
- X * add missing `break' in check_arity
- X *
- X * Revision 1.8 91/08/06 08:31:21 raymond
- X * Avoid infinite loop if file is corrupted.
- X * Better error-checking on configuration file (new output scheme).
- X *
- X * Revision 1.7 91/08/02 13:35:37 raymond
- X * Epsilonically better handling of environments that didn't end properly.
- X * Change return type of main() to keep gcc quiet.
- X * MSC support.
- X *
- X * Revision 1.6 91/07/28 21:08:53 raymond
- X * BeginTabs et al, FNote#, ENote#, NegateTotal, more unsupported codes
- X * Improve character tokens, Header, Footer
- X * Take care when people don't end lines with HRt
- X * Fix major bugs in endnote processing, footnote numbering (and nobody
- X * noticed!)
- X * More worries about signed characters.
- X *
- X * Revision 1.5 91/07/23 22:59:43 raymond
- X * Add COMMENT token, and some bug fixes.
- X *
- X * Revision 1.4 91/07/23 22:09:23 raymond
- X * Concessions to slightly non-ANSI compilers. (`const', `unsigned char')
- X * More patches for machines with signed characters.
- X * Fix blatant bug in hex constants. (Amazed nobody noticed.)
- X * New tags SetFn#, Header, Footer.
- X * Warning messages for unsupported tokens.
- X * Backslahes processed in character tags.
- X * Fixed(?) footnotes, endnotes, page length changes.
- X * Inserted missing `break's into the huge switch.
- X *
- X * Revision 1.3 91/07/12 15:39:44 raymond
- X * Spiffy Turbo C support.
- X * Some <stdlib.h>'s don't declare errno et al.
- X * Command line switches `-s' and `-n' added.
- X * More cute warning messages.
- X * Dots periodically emitted.
- X * Give the enum of token types a name, to placate QuickC.
- X * Fix problems with pitch changes and signed characters.
- X *
- X * Revision 1.2 91/06/22 08:18:22 raymond
- X * <process.h> and fputchar() aren't sufficiently portable.
- X * strerror() fails to exist on some so-called ANSI platforms.
- X * Removed assumption that characters are unsigned.
- X * Forgot to #include <stdarg.h>
- X *
- X */
- X
- X/************************************************************************
- X * PORTABILITY CONCERNS
- X ************************************************************************
- X *
- X * If possible, compile with unsigned characters. (Though I think
- X * I've taken care of all the places where I assumed characters are
- X * unsigned.)
- X *
- X * This program assumes that your compiler is fully ANSI-conformant.
- X * Depending on how non-conformant your compiler is, you may need to
- X * set the following symbols at compile time:
- X *
- X * NO_CONST -- set this if your compiler does not know what `const' means.
- X * Cdecl -- how to tag functions that are variadic.
- X *
- X * Cdecl is used if you need special declarations for variadic functions.
- X * This is used by IBM PC compilers so that you can make the default
- X * parameter passing Pascal-style or Fastcalls.
- X *
- X * Some very machine-dependent stuff happens when trying to open the
- X * descriptor file. Please read dopen.c as well.
- X */
- X
- X#ifdef NO_CONST
- X#define const
- X#endif
- X
- X#ifndef Cdecl /* default is nothing */
- X#define Cdecl
- X#endif
- X
- X/************************************************************************
- X * This program divides naturally into two parts.
- X *
- X * The first part reads in the descriptor file and builds the expansions
- X * for each of the identifiers listed above.
- X * This is the easy part.
- X *
- X * The second part reads the input file and uses the expansions collected
- X * in the first part to transform the file into the output.
- X * This is the hard part.
- X *
- X ************************************************************************/
- X
- X/* And now, the code.
- X * We start off with some obvious header files.
- X */
- X
- X#include <stdio.h>
- X#include <stdarg.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <ctype.h>
- X
- X/* Some platforms do not define these externals in stdlib.h */
- Xextern int Cdecl errno;
- Xextern char *Cdecl sys_errlist[];
- Xextern int Cdecl sys_nerr;
- X
- X/************************************************************************/
- X/* Some common idioms */
- X/************************************************************************/
- X
- X#define do_nothing /* twiddle thumbs */
- X
- X/************************************************************************/
- X/* Blowing up */
- X/************************************************************************/
- X
- X/* The function "error" accepts two arguments. A FILE pointer and
- X * a printf-style argument list. The printf-style arguments are
- X * printed to stderr. If the FILE is non-NULL, the the remaining
- X * contents of the file are printed as well (to provide context), up
- X * to 80 characters.
- X */
- X
- Xvoid Cdecl error(FILE *fp, char *fmt, ...)
- X{
- X int i;
- X va_list ap;
- X
- X fputs("Error: ", stderr);
- X va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
- X fputc('\n', stderr);
- X
- X if (fp) {
- X fprintf(stderr, "Unread text: ");
- X for (i = 0; i < 80 && !feof(fp); i++) fputc(getc(fp), stderr);
- X fputc('\n', stderr);
- X }
- X exit(1);
- X}
- X
- X/************************************************************************/
- X/* Command-line switches */
- X/************************************************************************/
- Xint silent = 0;
- Xint blipinterval = 1024; /* display blips every 1K */
- Xint blipcount;
- X
- X/************************************************************************/
- X/* Basic file manipulations */
- X/************************************************************************/
- X
- X/* We here define a few basic functions. Let us hope that the first
- X * three functions' names are self-descriptive.
- X */
- X
- Xint next_non_whitespace(FILE *fp)
- X{
- X register int c;
- X
- X while ((c = getc(fp)) != EOF && isspace(c)) do_nothing;
- X
- X return c;
- X}
- X
- Xint next_non_space_or_tab(FILE *fp)
- X{
- X register int c;
- X
- X while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t')) do_nothing;
- X
- X return c;
- X}
- X
- Xvoid eat_until_newline(FILE *fp)
- X{
- X register int c;
- X
- X while ((c = getc(fp)) != EOF && c != '\n') do_nothing;
- X}
- X
- X/* The function parse_hex grabs a (no-more-than-two-character) hex
- X * constant. Similarly, parse_octal does the same for octal constants.
- X */
- X
- Xint parse_hex(FILE *fp)
- X{
- X register int c, value;
- X
- X if (!isxdigit(c = toupper(getc(fp))))
- X error(fp, "Expecting a hex digit");
- X
- X if ((value = c - '0') > 9) value += '0' - 'A' + 10;
- X
- X if (!isxdigit(c = getc(fp))) { ungetc(c, fp); return value; }
- X
- X c = toupper(c);
- X value = (value << 4) + c - '0';
- X if (c > '9') value += '0' - 'A' + 10;
- X return value;
- X}
- X
- Xint parse_octal(FILE *fp, register int c)
- X{
- X register int value = c - '0';
- X
- X if ( (c = getc(fp)) < '0' || c > '7') { ungetc(c, fp); return value; }
- X
- X value = (value << 3) + c - '0';
- X
- X if ( (c = getc(fp)) < '0' || c > '7') { ungetc(c, fp); return value; }
- X
- X return (value << 3) + c - '0';
- X}
- X
- X
- X/************************************************************************/
- X/* Storing the input strings */
- X/************************************************************************/
- X
- X/* The input strings are allocated from a large pool we set up at
- X * startup. This lets us do our thing without having to fight
- X * with people like malloc and friends. This method does limit
- X * our configuration file to 32K, however. We hope that this is
- X * not a problem. (It also means that the program can be translated
- X * to almost any other language without too much difficulty.)
- X *
- X * Here's how it works.
- X *
- X * "pool" is an array of POOL_SIZE characters. The value of POOL_SIZE
- X * is flexible, but shouldn't exceed 65535, since that's the size of
- X * an IBM PC segment. If your configuration file is more than 64K,
- X * then there's probably something wrong.
- X *
- X * "pool_ptr" points to the next character in "pool" that hasn't been
- X * used for anything yet.
- X *
- X * "top_of_pool" points one character beyond the end of pool, so we can
- X * see if we've run out of memory.
- X *
- X * When we want to put something into the pool, we simply store into "pool"
- X * and increment "pool_ptr" appropriately.
- X *
- X * Access to these variables is done through the following functions,
- X * implemented as macros.
- X *
- X * "anchor_string()" is called before you start throwing things into
- X * the pool. It returns a pointer to the beginning of the string
- X * being built up.
- X *
- X * "add_to_string(c)" adds the character "c" to the string being built up.
- X *
- X * "finish_string()" gets ready for building a new string. We check
- X * that we did not overflow our pool. We pull the sneaky trick of
- X * a dummy else clause so that [1] "else"s match up properly if this
- X * is nested inside an "if" statement, [2] the semicolon gets eaten
- X * up correctly.
- X *
- X * "remove_string(s)" removes all strings from the one called "s" onwards.
- X *
- X */
- X
- X#define POOL_SIZE 32768U
- X
- Xchar pool[POOL_SIZE];
- Xchar *pool_ptr = pool;
- X#define top_of_pool (pool + POOL_SIZE)
- X
- X#define anchor_string() pool_ptr
- X#define add_to_string(c) (*pool_ptr++ = c)
- X#define finish_string() \
- X if (pool_ptr >= top_of_pool) error(NULL, "string pool overflow."); \
- X else do_nothing
- X#define remove_string(s) (pool_ptr = s)
- X
- X/************************************************************************/
- X/* Remembering the expansions */
- X/************************************************************************/
- X
- X/* The array "expansion" contains the expansions for everything.
- X * Everything is initialized to NULL.
- X *
- X * We set up things as follows:
- X * expansion[0..255] contain the expansions for the possible characters.
- X * expansion[256...] contain the expansions for the special codes.
- X *
- X * Make sure this table is kept in parallel with the names[] array
- X *
- X *
- X */
- X
- X/* name value When is it expanded? */
- X/* ---- --- -------------------- */
- Xenum token_type { /* Some compilers do not like unnamed enums */
- X typeout = 256, /* Typed out as soon as it is encountered */
- X BEGIN , /* Before the first character of the file */
- X END , /* After the last character of the file */
- X Comment , /* For wp2x-generated comments */
- X eComment ,
- X
- X PageNo , /* Current page number */
- X RomanPage , /* Set page number (to roman numerals) */
- X ArabicPage , /* Set page number (to arabic) */
- X
- X HSpace , /* unbreakable space (`Hard space') */
- X
- X Tab , /* Tab character */
- X BeginTabs , /* Begin tab settings */
- X
- X /* DO NOT CHANGE THE RELATIVE ORDER OF THESE FOUR TOKENS */
- X SetTab , /* Set normal tabstop at %d */
- X SetTabCenter , /* Set center tabstop at %d */
- X SetTabRight , /* Set right-justified tab at %d */
- X SetTabDecimal, /* Set decimal tab at %d */
- X
- X EndTabs , /* End tab settings */
- X
- X HPg , /* Hard page break */
- X CondEOP , /* Conditional end-of-page */
- X HRt , /* Hard return */
- X SRt , /* Soft return */
- X
- X NHyph , /* Normal hyphen */
- X NHyphE , /* Normal hyphen at the end of a line */
- X HHyph , /* Hard (nonbreakable) hyphen */
- X DHyph , /* Discretionary hyphen */
- X DHyphE , /* Discretionary hyphen at the end of a line */
- X NoHyphWord , /* Do not hyphenate this word */
- X
- X Marg , /* Margin settings */
- X TopMarg , /* Set top margin */
- X PageLength , /* Set page length */
- X
- X SS , /* Single spacing */
- X DS , /* Double spacing */
- X OHS , /* 1.5 spacing (One and a Half Spacing) */
- X TS , /* Triple spacing */
- X LS , /* Generic line spacing */
- X LPI , /* set 6 or 8 LPI */
- X
- X Bold , /* Begin boldface */
- X eBold , /* End boldface */
- X Und , /* Begin underline */
- X eUnd , /* End underline */
- X Red , /* Begin redline */
- X eRed , /* End redline */
- X Strike , /* Begin strikeout */
- X eStrike , /* End strikeout */
- X Rev , /* Begin reverse video */
- X eRev , /* End reverse video */
- X
- X Over , /* Overstrike */
- X eOver , /* [mythical "end overstroke" code] */
- X Sup , /* Superscript */
- X eSup , /* [mythical "end superscript" code] */
- X Sub , /* Subscript */
- X eSub , /* [mythical "end subscript" code] */
- X
- X UpHalfLine , /* Advance printer up 1/2 line */
- X DownHalfLine , /* Advance printer down 1/2 line */
- X AdvanceToHalfLine, /* Advance to absolute vertical position */
- X
- X Indent , /* Indented paragraph */
- X DIndent , /* Left-and-right-indented paragraph */
- X eIndent , /* End indented paragraph */
- X MargRel , /* Margin release (unknown argument) */
- X
- X Center , /* Center current line */
- X eCenter , /* End centering */
- X CenterHere , /* Center line around current column */
- X eCenterHere , /* End centering */
- X
- X Align , /* Begin alignment */
- X eAlign , /* End alignment */
- X AlignChar , /* Set alignment character */
- X FlushRight , /* Begin flush right */
- X eFlushRight , /* End flush right */
- X
- X Math , /* Begin math mode */
- X eMath , /* End math mode */
- X MathCalc , /* Begin math calc mode */
- X MathCalcColumn, /* Math calc column */
- X
- X SubTtl , /* Do subtotal */
- X IsSubTtl , /* Subtotal entry */
- X Ttl , /* Do total */
- X IsTtl , /* Total entry */
- X GrandTtl , /* Do grand total */
- X NegateTotal , /* Negate current total */
- X
- X Col , /* Begin column mode */
- X eCol , /* End column mode */
- X
- X Fn , /* Begin footnote */
- X eFn , /* End footnote */
- X En , /* Begin endnote */
- X eEn , /* End endnote */
- X SetFnNum , /* Set footnote number */
- X FNoteNum , /* Footnote number */
- X ENoteNum , /* Endnote number */
- X TableMarker , /* Table of contents or whatever marker */
- X
- X Hyph , /* Hyphenation on */
- X eHyph , /* off */
- X Just , /* Justification on */
- X eJust , /* off */
- X Wid , /* Widow/orphan protection on */
- X eWid , /* off */
- X HZone , /* Hyphenation zone */
- X DAlign , /* Decimal alignment character */
- X
- X Header , /* Begin header text */
- X eHeader , /* End header text */
- X Footer , /* Begin footer text */
- X eFooter , /* End footer text */
- X
- X Supp , /* Suppress formatting for one page */
- X CtrPg , /* Center page vertically */
- X
- X SetFont , /* Change pitch or font */
- X SetBin , /* Select paper bin (0, 1, ...) */
- X
- X PN , /* Page number position (PN+0 through PN+8) */
- X
- X/* Internal tokens for unsupported operations */
- X UnsupportedPlaceHolder = PN + 9,
- X SetPageNumberColumn,
- X SetTabs,
- X SetUnderlineMode,
- X DefineColumn,
- X SetFootnoteAttributes,
- X SetParagraphNumberingStyle,
- X NumberedParagraph,
- X BeginMarkedText,
- X EndMarkedText,
- X DefineMarkedText,
- X DefineIndexMark,
- X DefineMathColumns,
- X Obsolete,
- X ReservedCode,
- X UnknownCode,
- X LastToken
- X};
- X
- Xchar *expansion[LastToken];
- X
- X
- X/************************************************************************/
- X/* Naming the identifiers */
- X/************************************************************************/
- X/* Extreme care must be taken to ensure that this list parallels the list
- X * of token names above.
- X */
- X
- Xtypedef struct identifier {
- X char *name;
- X int arity;
- X} Identifier;
- X
- XIdentifier names[] = {
- X { "typeout", 0 },
- X { "BEGIN", 0 },
- X { "END", 0 },
- X { "Comment", 0 },
- X { "comment", 0 },
- X { "PageNo", 0 },
- X { "RomanPage", 1 },
- X { "ArabicPage", 1 },
- X { "HSpace", 0 },
- X { "Tab", 0 },
- X { "BeginTabs", 0 },
- X { "SetTab", 1 },
- X { "SetTabCenter", 1 },
- X { "SetTabRight", 1 },
- X { "SetTabDecimal", 1 },
- X { "EndTabs", 0 },
- X { "HPg", 0 },
- X { "CondEOP", 1 },
- X { "HRt", 0 },
- X { "SRt", 0 },
- X { "-", 0 }, /* NHyph */
- X { "--", 0 }, /* NHyphE */
- X { "=", 0 }, /* HHyph */
- X { "\\-", 0 }, /* DHyph */
- X { "\\--", 0 }, /* DHyphE */
- X { "NoHyphWord", 0 },
- X { "Marg", 2 },
- X { "TopMarg", 1 },
- X { "PageLength", 1 },
- X { "SS", 0 },
- X { "DS", 0 },
- X { "1.5S", 0 }, /* OHS */
- X { "TS", 0 },
- X { "LS", 1 },
- X { "LPI", 1 },
- X { "Bold", 0 },
- X { "bold", 0 },
- X { "Und", 0 },
- X { "und", 0 },
- X { "Red", 0 },
- X { "red", 0 },
- X { "Strike", 0 },
- X { "strike", 0 },
- X { "Rev", 0 },
- X { "rev", 0 },
- X { "Over", 0 },
- X { "over", 0 },
- X { "Sup", 0 },
- X { "sup", 0 },
- X { "Sub", 0 },
- X { "sub", 0 },
- X { "UpHalfLine", 0 },
- X { "DownHalfLine", 0 },
- X { "AdvanceToHalfLine", 2 },
- X { "Indent", 0 },
- X { "DIndent", 0 },
- X { "indent", 0 },
- X { "MarginRelease", 1 },
- X { "Center", 0 },
- X { "center", 0 },
- X { "CenterHere", 0 },
- X { "centerhere", 0 },
- X { "Align", 0 },
- X { "align", 0 },
- X { "AlignChar", 1 },
- X { "FlushRight", 0 },
- X { "flushright", 0 },
- X { "Math", 0 },
- X { "math", 0 },
- X { "MathCalc", 0 },
- X { "MathCalcColumn", 0 },
- X { "SubTotal", 0 },
- X { "IsSubTotal", 0 },
- X { "Total", 0 },
- X { "IsTotal", 0 },
- X { "GrandTotal", 0 },
- X { "NegateTotal", 0 },
- X { "Col", 0 },
- X { "col", 0 },
- X { "Fn", 0 },
- X { "fn", 0 },
- X { "En", 0 },
- X { "en", 0 },
- X { "SetFn#", 1 },
- X { "FNote#", 0 },
- X { "ENote#", 0 },
- X { "TableMarker", 0 },
- X { "Hyph", 0 },
- X { "hyph", 0 },
- X { "Just", 0 },
- X { "just", 0 },
- X { "Wid", 0 },
- X { "wid", 0 },
- X { "HZone", 2 },
- X { "DAlign", 1 },
- X { "Header", 0 },
- X { "header", 0 },
- X { "Footer", 0 },
- X { "footer", 0 },
- X { "Supp", 1 },
- X { "CtrPg", 0 },
- X { "SetFont", 2 },
- X { "SetBin", 1 },
- X { "PN0", 0 },
- X { "PN1", 0 },
- X { "PN2", 0 },
- X { "PN3", 0 },
- X { "PN4", 0 },
- X { "PN5", 0 },
- X { "PN6", 0 },
- X { "PN7", 0 },
- X { "PN8", 0 },
- X { NULL, 0 }, /* UnsupportedPlaceHolder -- keeps match_identifier happy */
- X { "set page number column", 0 },
- X { "extended tabs", 0 },
- X { "underline mode", 0 },
- X { "define column", 0 },
- X { "footnote attributes", 0 },
- X { "paragraph numbering style", 0 },
- X { "numbered paragraph", 0 },
- X { "begin marked text", 0 },
- X { "end marked text", 0 },
- X { "define marked text", 0 },
- X { "define index mark", 0 },
- X { "define math columns", 0 },
- X { "WPCorp obsolete", 0 },
- X { "WPCorp reserved", 0 },
- X { "WPCorp undefined", 0 },
- X};
- X
- X/* The file pointer "descriptor" points to our descriptor file
- X * and "input" points to our input file.
- X *
- X * Kinda makes sense that way.
- X */
- X
- XFILE *descriptor, *input;
- X
- X/* And the function match_identifier(s) takes a string and converts
- X * it to its corresponding integer. Or blows up if it couldn't
- X * find one.
- X */
- X
- Xint match_identifier(const char *s)
- X{
- X Identifier *I;
- X
- X /* Maybe it is a special character */
- X if (s[0] == '\'' && s[2] == '\'' && s[3] == '\0')
- X return (int) (unsigned char) s[1];
- X
- X /* Else it must be a multi-character guy */
- X for (I = names; I->name; I++)
- X if (!strcmp(I->name, s)) return typeout + (I - names);
- X
- X /* Otherwise, I don't know what to do with it */
- X error(descriptor, "Unknown identifier %s", s);
- X /*NOTREACHED*/
- X return 0;
- X}
- X
- X/* check_arity ensures that the expansion string is valid */
- Xvoid check_arity(int ident, char *t)
- X{
- X char *s;
- X int arity = 0;
- X if (ident > typeout) arity = names[ident-typeout].arity;
- X for (s = t; *s; s++) {
- X if (*s != '%') continue;
- X switch (*++s) {
- X case '\n':
- X if (s != t+1)
- X error(descriptor, "%s: `%%\\n' not at start of expansion",
- X names[ident-typeout].name);
- X break;
- X case '1':
- X case 'c':
- X if (arity < 1) goto bad_escape;
- X break;
- X case '2':
- X if (arity < 2) goto bad_escape;
- X break;
- X case '%':
- X break;
- X default:
- Xbad_escape:
- X error(descriptor, "%s: invalid escape `%%%c'", names[ident-typeout].name, *s);
- X }
- X }
- X}
- X
- X/************************************************************************/
- X/* Reading input from the descriptor file */
- X/************************************************************************/
- X
- X/* The macro igetc() gets a character from the input file.
- X * the macro dgetc() gets a character from the descriptor file.
- X*/
- X
- X#define igetc() getc(input)
- X#define dgetc() getc(descriptor)
- X
- X/* expand_backslash() is called when a backslash is encountered in
- X * the descriptor file. Its job is to parse a backslash-sequence.
- X * The usual C-escapes (\a \b \f \n \r \t \v) are understood, as
- X * well as the octal escape \000 [up to three octal digits] and
- X * the hex escape \xFF [up to two hex digits].
- X */
- X
- Xint expand_backslash(void) {
- X int c;
- X
- X switch (c = dgetc()) {
- X case 'a': c = '\a'; break;
- X case 'b': c = '\b'; break;
- X case 'f': c = '\f'; break;
- X case 'n': c = '\n'; break;
- X case 'r': c = '\r'; break;
- X case 't': c = '\t'; break;
- X case 'v': c = '\v'; break;
- X case 'x':
- X case 'X': c = parse_hex(descriptor); break;
- X case '0':
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7': c = parse_octal(descriptor, c); break;
- X default: /* c = c; */ break;
- X }
- X return c;
- X}
- X
- X/* The function read_identifier() attempts to match an identifier
- X * in the descriptor file. It returns EOF if the end of the descriptor
- X * file was reached, or the code of the identifier we found.
- X * (or blows up if an error was detected.)
- X * We build the identifier in "s", with the help of our
- X * pool-managing functions above, then discard it, immediately,
- X * since we don't use it any more.
- X */
- X
- Xint read_identifier(void)
- X{
- X register int c; /* A character we have read */
- X char *s; /* The identifier we are building */
- X int ident; /* The identifier we found */
- X
- X /* Skip over comments */
- X while ((c = next_non_whitespace(descriptor)) == '#')
- X eat_until_newline(descriptor);
- X
- X if (c == EOF) return EOF;
- X
- X /* At this point, "c" contains the first letter of a potential
- X * identifier. Let's see what it could possibly be.
- X */
- X s = anchor_string();
- X if (c == '\'') { /* a character token */
- X add_to_string(c);
- X if ((c = dgetc()) == '\\') c = expand_backslash();
- X add_to_string(c);
- X if ((c = dgetc()) != '\'')
- X error(descriptor, "Invalid character identifier");
- X add_to_string(c);
- X c = next_non_space_or_tab(descriptor);
- X } else do { /* a name token */
- X add_to_string(c);
- X c = next_non_space_or_tab(descriptor);
- X if (c == '\\') c = expand_backslash();
- X } while (c != EOF && c != '=' && c != '\n');
- X
- X if (c != '=') error(descriptor, "Identifier not followed by = sign");
- X /* A boo-boo. Something bad happened. */
- X
- X add_to_string('\0'); /* Make it a standard C string. */
- X finish_string();
- X
- X ident = match_identifier(s); /* Go find one. */
- X
- X remove_string(s); /* And we're done with it now. */
- X
- X return ident;
- X}
- X
- X/* The function grab_expansion() reads expansion text from the
- X * descriptor file and adds it to the pool, returning a pointer
- X * to the string it just created.
- X *
- X * After anchoring a new string, we look for the opening quotation
- X * mark, then start gobbling characters. Everything gets copied
- X * straight into the string.
- X *
- X */
- X
- Xchar *grab_expansion(void)
- X{
- X register int c; /* Characters being read */
- X char *s; /* The string we are building */
- X
- X s = anchor_string();
- X
- X if (next_non_whitespace(descriptor) != '\"')
- X error(descriptor, "Quotation mark expected");
- X
- X /* Now read the stream until we hit another quotation mark. */
- X
- X while ((c = dgetc()) != EOF && c != '\"') {
- X if (c == '\\') c = expand_backslash();
- X add_to_string(c);
- X }
- X add_to_string('\0');
- X finish_string();
- X return s;
- X}
- X
- X/* Ah, now with all of these beautiful functions waiting for us,
- X * we can now write our first Useful Function: do_descriptor_file.
- X * It reads the descriptor file and loads up the "expansion" array
- X * with the text expansions we are reading from the file.
- X *
- X * If we grabbed the expansion of a "typeout", we type it out
- X * and discard the string.
- X *
- X * We stop when the descriptor file runs dry.
- X *
- X */
- X
- Xvoid do_descriptor_file(void)
- X{
- X register int ident;
- X
- X while ((ident = read_identifier()) != EOF) {
- X expansion[ident] = grab_expansion();
- X if (ident == typeout && !silent) {
- X fputs(expansion[typeout], stderr); remove_string(expansion[typeout]);
- X expansion[typeout] = NULL;
- X } else check_arity(ident, expansion[ident]);
- X }
- X}
- X
- X/************************************************************************/
- X/* Reading from the input file */
- X/************************************************************************/
- X
- X/* The function verify(c) checks that the next character in the input
- X * stream is indeed "c". It eats the character, if all is well.
- X * If something went wrong, we complain to stderr, but keep going.
- X */
- X
- Xvoid verify(int c)
- X{
- X int d = igetc();
- X if (d != c) fprintf(stderr, "Warning: Expected %02X but received %02X.\n", c, d);
- X}
- X
- X/* The function gobble(n) simply eats "n" characters from the input
- X * file.
- X */
- Xvoid gobble(int n)
- X{
- X while (n--) (void) igetc();
- X}
- X
- Xint last_HRt = 0; /* most recent output was HRt */
- X
- X/* Processing a special code simply entails dumping its expansion.
- X * If the expansion is NULL, then we either
- X * [1] print nothing, if it is a code,
- X * [2] print the character itself, if it is an ASCII character.
- X *
- X * In dumping its expansion, we expand the following percent-escapes:
- X *
- X * The percent-escapes are:
- X * %\n -- newline if previous character was not a newline
- X * (meaningful only as first character in sequence)
- X * %1 -- first parameter, in decimal form
- X * %2 -- second parameter, in decimal form
- X * %c -- first parameter, in character form
- X * %% -- literal percent sign
- X *
- X * all other %-escapes are flagged as warnings (but should never occur,
- X * since they are trapped at the time the descriptor file is read.)
- X */
- Xvoid process(int c, int d1, int d2)
- X{
- X char *s;
- X static int last_newline = 0;
- X
- X last_HRt = 0; /* the killer switch sets this */
- X
- X if (expansion[c] == NULL) { /* invent a default action */
- X if (c >= ' ' && c < 128) {
- X putchar(c); /* regular characters emit themselves */
- X last_newline = 0;
- X return;
- X } else if (c < 256) { /* single character */
- X expansion[c] = anchor_string(); /* emits itself */
- X add_to_string(c); add_to_string('\0');
- X finish_string();
- X if (!silent) fprintf(stderr, "Warning: No expansion for %02X (%c)\n", c, c);
- X } else { /* provide null expansion */
- X expansion[c] = "";
- X if (!silent) {
- X fprintf(stderr, "Warning: No expansion for %s\n", names[c-typeout].name);
- X }
- X }
- X }
- X
- X s = expansion[c];
- X if (!*s) return; /* the rest of the code assumes non-null string */
- X do {
- X if (*s != '%') putchar(*s++);
- X else {
- X s++;
- X switch (*s++) {
- X case '\n':
- X if (!last_newline) putchar('\n'); break;
- X case '1':
- X printf("%d", d1); break;
- X case '2':
- X printf("%d", d2); break;
- X case 'c':
- X putchar(d1); break;
- X case '%':
- X putchar('%'); break;
- X default:
- X fprintf(stderr, "Internal error: Invalid escape, %%%c\n", s[-1]);
- X break;
- X }
- X }
- X } while (*s);
- X last_newline = s[-1] == '\n';
- X}
- X
- X#define process0(c) process(c,0,0)
- X#define process1(c,a) process(c,a,0)
- X#define process2(c,a,b) process(c,a,b)
- X
- Xvoid unsupported(int c)
- X{
- X if (!silent && !expansion[c]) {
- X expansion[c] = "";
- X fprintf(stderr, "Warning: `%s' code not supported\n", names[c-typeout].name);
- X }
- X process0(Comment); fputs(names[c-typeout].name, stdout); process0(eComment);
- X}
- X
- X/* The function gobble_until(c) eats characters from the input file
- X * until it reaches a c or reaches EOF.
- X */
- Xvoid gobble_until(int c)
- X{
- X int i;
- X while ((i = igetc()) != EOF && (int) (unsigned char) i != c) do_nothing;
- X}
- X
- X/* line_spacing(l) is called whenever we hit a line-spacing-change command.
- X * The argument is the desired line spacing, multiplied by two.
- X * So single spacing gets a 2, 1.5 spacing gets a 3, etc.
- X */
- Xvoid line_spacing(int l)
- X{
- X switch (l) {
- X case 2: process0(SS); break;
- X case 3: process0(OHS); break;
- X case 4: process0(DS); break;
- X case 6: process0(TS); break;
- X default: process1(LS, l); break;
- X }
- X}
- X
- Xint environment_status = 0; /* cleanup at HRt */
- Xvoid leave_environment(int force_HRt) {
- X if (environment_status) {
- X process0(environment_status);
- X environment_status = 0;
- X }
- X if (force_HRt && !last_HRt) process0(HRt);
- X}
- X
- X/* The "note_status" flag has one of three values:
- X * 0 if we are not inside a note
- X * 1 if we are inside a footnote
- X * 2 if we are inside an endnote
- X *
- X * The function handle_note() is called to deal with footnotes and
- X * endnotes. It adjusts the note_status accordingly.
- X */
- X
- Xint note_status = 0;
- X
- Xvoid handle_note(void)
- X{
- X if (note_status) {
- X leave_environment(1); process0(note_status); note_status = 0;
- X } else { /* Decide whether it is an endnote or a footnote */
- X if (igetc() & 2) { process0(En); note_status = eEn; gobble(5); }
- X else { process0(Fn); note_status = eFn; gobble(7); }
- X verify(0xFF);
- X gobble(2); /* margins */
- X }
- X}
- X
- X/* The tab_table is a bit field. Each set bit represents a tabstop.
- X * Note, however, that the bits are counted from MSB to LSB.
- X *
- X * The tab_attribute_table is a nybble field. The n'th nybble represents
- X * the attributes of the n'th tabstop.
- X */
- Xunsigned char tab_table[32];
- Xunsigned char tab_attribute_table[20];
- Xint next_attribute;
- X
- Xvoid process_tab_attribute(int i) {
- X int b;
- X
- X if (next_attribute & 1) b = tab_attribute_table[next_attribute/2] & 3;
- X else b = (tab_attribute_table[next_attribute/2] / 16) & 3;
- X next_attribute++;
- X
- X /* Bottom two bites define what kind of tab.
- X * Bit 2 is set if we need dot filling.
- X * Bit 3 is unused.
- X * We `&3' above because we won't support dot filling.
- X */
- X process1(SetTab + b, i);
- X}
- X
- Xvoid process_tab_table(void) {
- X int i;
- X next_attribute = 0;
- X
- X process0(BeginTabs);
- X for (i = 0; i < 32; i++) {
- X if (tab_table[i] == 0) continue; /* early out */
- X if (tab_table[i] & 0x80) process_tab_attribute(i * 8 + 0);
- X if (tab_table[i] & 0x40) process_tab_attribute(i * 8 + 1);
- X if (tab_table[i] & 0x20) process_tab_attribute(i * 8 + 2);
- X if (tab_table[i] & 0x10) process_tab_attribute(i * 8 + 3);
- X if (tab_table[i] & 0x08) process_tab_attribute(i * 8 + 4);
- X if (tab_table[i] & 0x04) process_tab_attribute(i * 8 + 5);
- X if (tab_table[i] & 0x02) process_tab_attribute(i * 8 + 6);
- X if (tab_table[i] & 0x01) process_tab_attribute(i * 8 + 7);
- X }
- X process0(EndTabs);
- X}
- X
- Xvoid handle_tabs(void) {
- X /* pad the tables to force no new tabs, and left tabs everywhere */
- X memset(tab_table, 0, sizeof(tab_table));
- X memset(tab_attribute_table, 0, sizeof(tab_attribute_table));
- X
- X fread(tab_table, 20, 1, input); /* old-style tabs */
- X process_tab_table();
- X}
- X
- Xvoid handle_extended_tabs(void) {
- X fread(tab_table, 32, 1, input);
- X fread(tab_attribute_table, 20, 1, input);
- X process_tab_table();
- X}
- X
- X/* The FF_status flag tells us what we should do when we encounter an 0xFF.
- X * It contains the token code of the active code, or 0 if no code is active.
- X */
- X
- Xint FF_status = 0;
- X
- Xvoid handle_FF(void)
- X{
- X if (FF_status) { /* finish header/footer */
- X leave_environment(1);
- X process0(FF_status);
- X gobble(2);
- X verify(0xD1);
- X FF_status = 0;
- X } else process0(0xFF);
- X}
- X
- X/* The function process_token does all of the real work.
- X * Given the first character of a token, we eat up everything
- X * that belongs to that token. This routine might be called
- X * recursively, since some tokens are defined in terms of other
- X * tokens. (For example, the subscript code is expanded as
- X * [Sub] <character being subscripted> [sub]
- X * and the <character being subscripted> might involve other token
- X * expansions; specifically, it might be an IBM Extended character.)
- X *
- X * Luckily, most of our tokens are not recursive. The macro
- X * bracket(before, after)
- X * does the recursive stuff for us, bracketing the next token
- X * between expansions of "before" and "after".
- X *
- X */
- X
- X#define bracket(before,after) process0(before); process_token(); \
- X process0(after);
- X
- Xint process_token(void)
- X{
- X int c = igetc();
- X
- X if (c == EOF) return 0;
- X
- X c = (int) (unsigned char) c;
- X
- X if (!--blipcount && !silent) {
- X blipcount = blipinterval;
- X putc('.', stderr);
- X }
- X
- X switch (c) { /* Codes listed in numerical rather than logical order */
- X
- X case 0x02: process0(PageNo); break; /* Page number */
- X
- X case 0x09: process0(Tab); break; /* Tab character */
- X
- X case 0x8C: /* Soft page break after a HRt */
- X case 0x0A: /* Hard Return */
- X last_HRt = 0; leave_environment(1); last_HRt = 1; break;
- X case 0x0B: /* Soft page break after a SRt */
- X case 0x0D: process0(SRt); break; /* Soft Return */
- X
- X case 0x0C: process0(HPg); break; /* Hard Page */
- X
- X case '-' : process0(HHyph); break; /* Nonbreaking hyphen */
- X
- X case 0x80: break; /* NOP */
- X case 0x81: process0(Just); break; /* Right justification */
- X case 0x82: process0(eJust); break; /* Ragged right */
- X case 0x83: /* End centering */
- X case 0x84: leave_environment(0); break; /* End aligned text */
- X case 0x85: process0(MathCalc); break; /* Begin math calc */
- X case 0x86: process0(CtrPg); break; /* Center page vertically */
- X case 0x87: process0(Col); break; /* Begin column mode */
- X case 0x88: process0(eCol); break; /* End column mode */
- X case 0x89: process0(Tab); break; /* Tab after right margin */
- X case 0x8A: process0(Wid); break; /* Widow/orphan protection */
- X case 0x8B: process0(eWid); break; /* Allow widows/orphans */
- X/* case 0x8C: see 0x0A */
- X case 0x8D: /* Footnote/Endnote number */
- X process0(note_status == eFn ? FNoteNum : ENoteNum); break;
- X case 0x8E:
- X case 0x8F: unsupported(ReservedCode); break; /* Reserved codes */
- X case 0x90: process0(Red); break; /* Begin redline */
- X case 0x91: process0(eRed); break; /* End redline */
- X case 0x92: process0(Strike); break; /* Begin strikeout */
- X case 0x93: process0(eStrike); break; /* End strikeout */
- X case 0x94: process0(Und); break; /* Begin underlining */
- X case 0x95: process0(eUnd); break; /* End underlining */
- X case 0x96: process0(Rev); break; /* Begin reverse video */
- X case 0x97: process0(eRev); break; /* End reverse video */
- X case 0x98: process0(TableMarker); break;/* Table of something marker */
- X case 0x99: bracket(Over, eOver); break; /* Overstrike */
- X case 0x9A: process0(NoHyphWord); break;/* Do not hyphenate this word */
- X case 0x9B: break; /* End of generated text */
- X case 0x9C: process0(eBold); break; /* End boldface */
- X case 0x9D: process0(Bold); break; /* Begin boldface */
- X case 0x9E: process0(eHyph); break; /* Forbid hyphenation */
- X case 0x9F: process0(Hyph); break; /* Allow hyphenation */
- X case 0xA0: process0(HSpace); break; /* Hard space */
- X case 0xA1: process0(SubTtl); break; /* Do subtotal */
- X case 0xA2: process0(IsSubTtl); break; /* Subtotal entry */
- X case 0xA3: process0(Ttl); break; /* Do total */
- X case 0xA4: process0(IsTtl); break; /* Total entry */
- X case 0xA5: process0(GrandTtl); break; /* Do grand total */
- X case 0xA6: process0(MathCalcColumn); break; /* Math calc column */
- X case 0xA7: process0(Math); break; /* Begin math mode */
- X case 0xA8: process0(eMath); break; /* End math mode */
- X case 0xA9: process0(NHyph); break; /* Normal breakable hyphen */
- X case 0xAA: /* Hyphen at end of line */
- X case 0xAB: process0(NHyphE); break; /* Hyphen at end of page */
- X case 0xAC: process0(DHyph); break; /* Discretionary hyphen */
- X case 0xAD: /* Discretionary hyphen at EOLn */
- X case 0xAE: process0(DHyphE); break; /* Discretionary hyphen at EOPg */
- X case 0xAF: /* EOT columns and EOLn */
- X case 0xB0: break; /* EOT columns and EOPg */
- X
- X case 0xB1: process0(NegateTotal); break; /* Negate current total */
- X
- X case 0xBC: bracket(Sup, eSup); break; /* Superscript */
- X case 0xBD: bracket(Sub, eSub); break; /* Subscript */
- X case 0xBE: process0(UpHalfLine); break; /* Advance 1/2 line up */
- X case 0xBF: process0(DownHalfLine); break; /* Advance 1/2 line down */
- X
- X case 0xC0: gobble(2); c = igetc(); /* Margin change */
- X process2(Marg, c, igetc()); verify(0xC0); break;
- X
- X case 0xC1: gobble(1); line_spacing(igetc()); verify(0xC1); break;
- X /* Line spacing change */
- X
- X case 0xC2: process1(MargRel, igetc()); /* Margin release */
- X verify(0xC2); break;
- X
- X
- X case 0xC3: /* Center text */
- X leave_environment(0);
- X switch (igetc()) {
- X case 0: process0(Center); /* Center between margins */
- X environment_status = eCenter; break;
- X case 1: /* Center around current column */
- X process0(CenterHere);
- X environment_status = eCenterHere; break;
- X }
- X gobble(2); verify(0xC3); break;
- X
- X case 0xC4: /* Align or Flush Right */
- X leave_environment(0);
- X c = igetc();
- X /* if high bit on c is set, then dot fill. (Ignore) */
- X switch (c & 0x7f) {
- X case 0x0C:
- X case 0x0A: process1(FlushRight, igetc());/* alignment col */
- X environment_status = eFlushRight;
- X break;
- X default: process2(Align, c, igetc());/* alignment column */
- X environment_status = eAlign;
- X break;
- X }
- X gobble(1); /* trash */
- X verify(0xC4);
- X break;
- X
- X case 0xC5: gobble(2); c = igetc(); /* Hyphenation zone */
- X process2(HZone, c, igetc()); verify(0xC5); break;
- X
- X case 0xC6: gobble(1); /* Page number position */
- X process0(PN + igetc()); verify(0xC6); break;
- X
- X case 0xC7: gobble(2); c = igetc(); /* New page number */
- X c = (c<<8) + (unsigned char)igetc();
- X process1( (c&0x8000) ? RomanPage : ArabicPage, c&0x7fff);
- X verify(0xC7); break;
- X
- X case 0xC8: gobble(3); /* Set Page number column */
- X /* next 3 bytes are <left> <center> <right> */
- X gobble(3);
- X unsupported(SetPageNumberColumn);
- X verify(0xC8); break;
- X
- X case 0xC9: gobble(20); /* Set tabs */
- X handle_tabs();
- X verify(0xC9); break;
- X
- X case 0xCA: process1(CondEOP, igetc()); /* Conditional end of page */
- X verify(0xCA); break;
- X
- X case 0xCB: /* Set pitch or font */
- X gobble(2); /* old pitch and font */
- X c = igetc();
- X process2(SetFont, c, igetc()); /* pitch and font number */
- X /* negative pitch means proportional font */
- X verify(0xCB); break;
- X
- X case 0xCC: /* Indented paragraph */
- X leave_environment(0);
- X gobble(1); process1(Indent, igetc()); verify(0xCC);
- X environment_status = eIndent; break;
- X /* (really: Temporary margin) */
- X
- X case 0xCD: /* Indented paragraph (obsolete) */
- X leave_environment(0);
- X process1(Indent, igetc()); verify(0xCD);
- X environment_status = eIndent; break;
- X /* (really: Temporary margin) */
- X
- X case 0xCE: gobble(1); process1(TopMarg, igetc()); /* Set top margin */
- X verify(0xCE); break;
- X
- X case 0xCF: /* Suppress headers/footers for this page */
- X process1(Supp, (unsigned char)igetc());
- X verify(0xCF); break;
- X
- X case 0xD0: gobble(2); /* old form length */ /* Set page length */
- X process1(PageLength, igetc()); /* lines per page */
- X gobble(1); /* new page length */
- X verify(0xD0); break;
- X
- X case 0xD1: /* header/footer */
- X c = igetc(); /* def byte */
- X gobble(1); /* old half-lines */
- X if (c&2) { process0(Footer); FF_status = eFooter; }
- X else { process0(Header); FF_status = eHeader; }
- X verify(0xFF); verify(0xFF); /* separator */
- X gobble(2); /* left and right margin */
- X break; /* continue processing */
- X
- X case 0xD2: gobble(5); /* obsolete footnote */
- X unsupported(Obsolete);
- X gobble_until(0xD2);
- X break;
- X
- X case 0xD3: gobble(2); /* obsolete `set footnote number' */
- X unsupported(Obsolete);
- X verify(0xD3);
- X break;
- X
- X case 0xD4: /* Advance to half line number */
- X c = igetc(); /* current line number */
- X process2(AdvanceToHalfLine, c, igetc());/* desired line # */
- X verify(0xD4); break;
- X
- X case 0xD5: gobble(1); process1(LPI, igetc()); /* Set LPI (6 or 8) */
- X verify(0xD5); break;
- X
- X case 0xD6: /* set extended tabs */
- X /* next 4 bytes are <old start><old increment>
- X <new start><new increment> */
- X gobble(4);
- X unsupported(SetTabs);
- X verify(0xD6); break;
- X
- X case 0xD7: gobble(63); /* Define math columns */
- X unsupported(DefineMathColumns);
- X verify(0xD7); break;
- X
- X case 0xD8: gobble(1); process1(AlignChar, igetc());
- X verify(0xD8); break; /* Set alignment character */
- X
- X case 0xD9: gobble(2); /* obsolete margin release */
- X unsupported(Obsolete);
- X verify(0xD9);
- X break;
- X
- X case 0xDA: gobble(1+1); /* Set underline mode */
- X /* second byte is a bit field.
- X * 1 = double-underline (default single),
- X * 2 = underline spaces (default don't)
- X */
- X unsupported(SetUnderlineMode);
- X verify(0xDA); break;
- X
- X case 0xDB: /* Set sheet feeder bin */
- X gobble(1); process1(SetBin, igetc());
- X verify(0xDB); break;
- X
- X /* We ignore these codes, since they are followed by an 0x0C or an 0x8C */
- X case 0xDC: gobble(7); verify(0xDC); break; /* End-of-page codes */
- X
- X case 0xDD: gobble(22); /* define columns */
- X unsupported(DefineColumn);
- X verify(0xDD);
- X
- X case 0xDE: environment_status = 0; /* End indented paragraph */
- X gobble(2); process0(eIndent); verify(0xDE); break;
- X
- X case 0xDF: /* invisible characters */
- X gobble_until(0xDF);
- X break;
- X
- X case 0xE0: /* Doubly-indented paragraph */
- X leave_environment(0);
- X gobble(1); process1(DIndent, igetc()); verify(0xE0);
- X environment_status = eIndent; break;
- X
- X case 0xE1: process0((unsigned char)igetc()); verify(0xE1); break;
- X /* IBM character */
- X
- X case 0xE2: handle_note(); break; /* footnote or endnote */
- X
- X case 0xE3: gobble(74+74); /* footnote attributes */
- X unsupported(SetFootnoteAttributes);
- X verify(0xE3);
- X break;
- X
- X case 0xE4: gobble(2); /* old */ /* set footnote number */
- X /* bit 7 of second byte doesn't count, and the value
- X * is offset by one.
- X */
- X c = igetc() & 0x3f;
- X c = (c << 7) + (igetc() & 0x7f);
- X process1(SetFnNum, 1 + c);
- X verify(0xE4);
- X break;
- X
- X case 0xE5: /* paragraph numbering style */
- X gobble(7+7+7+7);
- X unsupported(SetParagraphNumberingStyle);
- X verify(0xE5);
- X break;
- X
- X case 0xE6: /* paragraph number */
- X gobble(2+7);
- X unsupported(NumberedParagraph);
- X verify(0xE6);
- X break;
- X
- X case 0xE9: /* begin marked text */
- X gobble(6);
- X unsupported(BeginMarkedText);
- X verify(0xE9);
- X break;
- X
- X case 0xEA: /* end marked text */
- X unsupported(EndMarkedText);
- X gobble_until(0xEA);
- X break;
- X
- X case 0xEB: /* define marked text */
- X gobble(30);
- X unsupported(DefineMarkedText);
- X verify(0xEB);
- X break;
- X
- X case 0xEC: /* define index mark */
- X gobble(2);
- X unsupported(DefineIndexMark);
- X verify(0xEC);
- X break;
- X
- X case 0xED: /* Table of authorities */
- X unsupported(DefineIndexMark);
- X gobble_until(0xED);
- X break;
- X case 0xEE: /* paragraph number def */
- X gobble(42);
- X unsupported(SetParagraphNumberingStyle);
- X verify(0xEE);
- X break;
- X
- X case 0xEF: /* paragraph number */
- X gobble(16);
- X unsupported(NumberedParagraph);
- X verify(0xEF);
- X break;
- X
- X case 0xF1: gobble(32 + 20); /* Tab settings */
- X handle_extended_tabs();
- X verify(0xF1);
- X break;
- X
- X case 0xF3: /* column definition */
- X gobble(98);
- X unsupported(DefineColumn);
- X verify(0xF3);
- X break;
- X
- X
- X case 0xB2:
- X case 0xB3:
- X case 0xB4:
- X case 0xB5:
- X case 0xB6:
- X case 0xB7:
- X case 0xB8:
- X case 0xB9:
- X case 0xBA:
- X
- X case 0xF0:
- X
- X case 0xF2:
- X case 0xF4:
- X case 0xF5:
- X case 0xF6:
- X case 0xF7:
- X case 0xF8:
- X case 0xF9:
- X case 0xFA:
- X case 0xFB:
- X case 0xFC:
- X case 0xFD:
- X case 0xFE: unsupported(UnknownCode); break; /* undefined codes */
- X
- X case 0xFF: handle_FF(); break;
- X
- X default: process0(c); break;
- X }
- X return 1;
- X}
- X
- X/* Now do the other Useful Function.
- X */
- Xvoid process_input(void)
- X{
- X process0(BEGIN);
- X while (process_token()) do_nothing;
- X process0(END);
- X}
- X
- X
- X/************************************************************************/
- X/* The main program */
- X/************************************************************************/
- X
- X/* First, a pretty little function which tries to open a file and
- X * complains loudly if it cannot.
- X */
- X
- XFILE *efopen(const char *s, const char *m)
- X{
- X FILE *fp = fopen(s, m);
- X
- X if (fp == NULL) {
- X fprintf(stderr, "Error: Cannot open %s", s);
- X if (errno > 0 && errno < sys_nerr)
- X fprintf(stderr, " (%s)\n", s, sys_errlist[errno]);
- X fprintf(stderr, "\n");
- X exit(1);
- X }
- X
- X return fp;
- X}
- X
- X#include "dopen.c" /* ickiness with file opening */
- X
- X/* Our main program does very little, really.
- X *
- X * After checking the command line, it proceeds to open the descriptor
- X * file in text mode, and the input file in binary mode.
- X * It then calls our two Useful Functions in turn, closing each file
- X * after it has served its purpose.
- X */
- X
- Xint Cdecl main(int argc, char **argv)
- X{
- X while (--argc && **++argv == '-') {
- X while (*++*argv) switch (**argv) {
- X case 's': silent = 1; break;
- X case 'n': blipinterval = atoi(&argv[0][1]); goto finarg;
- X default: goto usage;
- X }
- Xfinarg: ;
- X }
- X blipcount = blipinterval;
- X
- X if (argc != 2) {
- Xusage:
- X fprintf(stderr, "usage: wp2x descriptor input > output\n");
- X exit(2);
- X }
- X
- X dopen(argv[0]);
- X input = efopen(argv[1], "rb");
- X
- X do_descriptor_file();
- X fclose(descriptor);
- X
- X process_input();
- X fclose(input);
- X return 0;
- X}
- END_OF_FILE
- if test 51514 -ne `wc -c <'wp2x.c'`; then
- echo shar: \"'wp2x.c'\" unpacked with wrong size!
- fi
- # end of 'wp2x.c'
- fi
- echo shar: End of archive 3 \(of 3\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- exit 0 # Just in case...
-